/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.classdiagram;

import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartFactory;
import org.eclipse.uml2.uml.Abstraction;
import org.eclipse.uml2.uml.Association;
import org.eclipse.uml2.uml.Comment;
import org.eclipse.uml2.uml.Component;
import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.DataType;
import org.eclipse.uml2.uml.Dependency;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.Enumeration;
import org.eclipse.uml2.uml.EnumerationLiteral;
import org.eclipse.uml2.uml.Extension;
import org.eclipse.uml2.uml.Generalization;
import org.eclipse.uml2.uml.InstanceSpecification;
import org.eclipse.uml2.uml.Interface;
import org.eclipse.uml2.uml.InterfaceRealization;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.OpaqueExpression;
import org.eclipse.uml2.uml.Operation;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.PackageImport;
import org.eclipse.uml2.uml.PrimitiveType;
import org.eclipse.uml2.uml.Profile;
import org.eclipse.uml2.uml.ProfileApplication;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Realization;
import org.eclipse.uml2.uml.Reception;
import org.eclipse.uml2.uml.RedefinableTemplateSignature;
import org.eclipse.uml2.uml.Signal;
import org.eclipse.uml2.uml.Slot;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.TemplateBinding;
import org.eclipse.uml2.uml.TemplateParameter;
import org.eclipse.uml2.uml.TemplateSignature;
import org.eclipse.uml2.uml.Usage;

import com.cea.papyrus.core.editor.EditpartFactoryBase;
import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.core.editpart.AnchorEditPart;
import com.cea.papyrus.core.editpart.GraphEdgeEditPart;
import com.cea.papyrus.core.editpart.GraphNodeWithSemanticEditPart;
import com.cea.papyrus.core.editpart.OpaqueExpressionEditPart;
import com.cea.papyrus.core.editpart.StereotypePropertiesDisplayEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.AbstractionEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.AssociationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.ClassDiagramEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.ClassEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.CommentEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.ComponentEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.ConstraintEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.DataTypeEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.DependencyEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.ElementImportEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.EnumerationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.EnumerationLiteralEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.ExtensionEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.GeneralizationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.InstanceSpecificationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.InterfaceEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.InterfaceRealizationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.LinkInstanceSpecificationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.ModelEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.OperationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.PackageEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.PackageImportEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.PrimitiveTypeEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.ProfileApplicationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.ProfileEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.PropertyEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.RealizationEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.ReceptionEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.RedefinableTemplateSignatureEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.SignalEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.SlotEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.StereotypeEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.TemplateBindingEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.TemplateParameterEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.TemplateSignatureEditPart;
import com.cea.papyrus.diagram.classdiagram.editpart.UsageEditPart;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;
import com.cea.papyrus.diagraminterchange2.di2.GraphEdge;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;

/**
 * Factory to create all editparts.
 * 
 * @author Patrick Tessier
 */

public class ClassDiagramGraphicalEditPartsFactory extends EditpartFactoryBase implements EditPartFactory
{

	/**
	 * 
	 */
	protected ModelManager modelManager;
	
	/**
	 * 
	 * 
	 * @param modelManager 
	 */
	public ClassDiagramGraphicalEditPartsFactory(ModelManager modelManager){
		this.modelManager=modelManager;
	}
	/*
	 * (non-Javadoc)
	 * @see org.eclipse.gef.EditPartFactory#createEditPart(org.eclipse.gef.EditPart, java.lang.Object)
	 */
	/**
	 * 
	 * 
	 * @param obj 
	 * @param context 
	 * 
	 * @return 
	 */
	public EditPart createEditPart(EditPart context, Object obj)
	{
		//new mechanism
		EditPart result= getEditPartFromProperty(context, obj,modelManager);
		if (result!=null){
			return result;
		}
		
		// OLD mechanism : do not delete it to keep compatibility
		// to identify the good editpart we need the nature of the object graphEdge or graphNode and
		// uml Elment connected
		// case of a diagram
		
		if (obj instanceof Diagram) {
			return new ClassDiagramEditPart((Diagram)obj,modelManager);
		} else if(obj instanceof GraphNode){
			if (((Uml1SemanticModelBridge)((GraphNode)obj).getSemanticModel())==null){
				if(((GraphNode)obj).getSemanticParent()!=null){
					return new StereotypePropertiesDisplayEditPart((GraphNode)obj,modelManager);
				}
				return new AnchorEditPart((GraphNode)obj,modelManager);}
			if ((((Uml1SemanticModelBridge)((GraphNode)obj).getSemanticModel()).getElement())==null){
				return new GraphNodeWithSemanticEditPart((GraphNode)obj,modelManager);}
			Element elt =((Uml1SemanticModelBridge)((GraphNode)obj).getSemanticModel()).getElement();
			return searchEditPart((GraphNode)obj, elt);
		}

		//case of a graphEdge
		else if (obj instanceof GraphEdge){
			if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel())!=null){
				if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof ElementImport){
					return new ElementImportEditPart((GraphEdge)obj,modelManager);}
				else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof PackageImport){
					return new PackageImportEditPart((GraphEdge)obj,modelManager);}
				else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof ProfileApplication){
					return new ProfileApplicationEditPart((GraphEdge)obj,modelManager);}
				else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Generalization){
					return new GeneralizationEditPart((GraphEdge)obj,modelManager);}
				else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Extension){
					return new ExtensionEditPart((GraphEdge)obj,modelManager);}
				else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof InterfaceRealization){
					return new InterfaceRealizationEditPart((GraphEdge)obj,modelManager);}
				else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Realization){
					return new RealizationEditPart((GraphEdge)obj,modelManager);}
				else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Abstraction){
					return new AbstractionEditPart((GraphEdge)obj,modelManager);}
				else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Usage){
					return new UsageEditPart((GraphEdge)obj,modelManager);}
				else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Dependency){
					return new DependencyEditPart((GraphEdge)obj,modelManager);}
				else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof Association){
					return new AssociationEditPart((GraphEdge)obj,modelManager);}
				else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof InstanceSpecification){
					return new LinkInstanceSpecificationEditPart((GraphEdge)obj,modelManager);}
				else if (((Uml1SemanticModelBridge)((GraphEdge)obj).getSemanticModel()).getElement() instanceof TemplateBinding) {
					return new TemplateBindingEditPart((GraphEdge)obj, modelManager);}
			}
			else{
				GraphEdge ge=(GraphEdge)obj;
				return new GraphEdgeEditPart(ge,modelManager);		
			}
		}

		return null;
	}
	
	/**
	 * Create the good Edit part from the the GraphNode and the Element.
	 * 
	 * @param graphNode 
	 * @param elt 
	 * 
	 * @return 
	 * @deprecated
	 */
	public EditPart searchEditPart(GraphNode graphNode, Element elt){
		
		
		//Component
		if (elt instanceof Component){
			return new ComponentEditPart(graphNode,modelManager);}
		// Templates
		
		if (elt instanceof RedefinableTemplateSignature) {
			return new RedefinableTemplateSignatureEditPart(graphNode, modelManager) ;
		}
		
		if (elt instanceof TemplateSignature) {
			return new TemplateSignatureEditPart(graphNode, modelManager) ;
		}
		
		if (elt instanceof TemplateParameter) {
			return new TemplateParameterEditPart(graphNode, modelManager) ;
		}
		
		//Type elements
		if (elt instanceof ElementImport){
			// in the case of element Import, we need to recall this method
			return searchEditPart(graphNode, ((ElementImport)elt).getImportedElement());
		}
		if (elt instanceof Interface){
			return new InterfaceEditPart(graphNode,modelManager);}
		//Constraint
		if (elt instanceof Constraint){
			return new ConstraintEditPart(graphNode,modelManager);}
//		signal
		if (elt instanceof Signal){
			return new SignalEditPart(graphNode,modelManager);}		

		//primitive Type
		if (elt instanceof PrimitiveType){
			return new PrimitiveTypeEditPart(graphNode,modelManager);}			

		//Enumeration
		if (elt instanceof Enumeration){
			return new EnumerationEditPart(graphNode,modelManager);}

		//DataType
		if (elt instanceof DataType){
			return new DataTypeEditPart(graphNode,modelManager);}
		//		model
		if (elt instanceof Model){
			return new ModelEditPart(graphNode,modelManager);}

		//profile
		if (elt instanceof Profile){
			return new ProfileEditPart(graphNode,modelManager);}

		//this is a package element???
		if (elt instanceof Package){
			return new PackageEditPart(graphNode,modelManager);}

		//Stereotype
		if (elt instanceof Stereotype){
			return new StereotypeEditPart(graphNode,modelManager);}

		//Class
		if (elt instanceof org.eclipse.uml2.uml.Class){
			return new ClassEditPart(graphNode,modelManager);}
		
//		Enumeration Literal
		if (elt instanceof EnumerationLiteral){
			return new EnumerationLiteralEditPart(graphNode,modelManager);}

		
		//InstanceSpecification
		if (elt instanceof InstanceSpecification){
			return new InstanceSpecificationEditPart(graphNode,modelManager);
		}
		
//		Reception
		if (elt instanceof Reception){
			return new ReceptionEditPart(graphNode,modelManager);}


		//Operation
		if (elt instanceof Operation){
			return new OperationEditPart(graphNode,modelManager);}

		//Property
		if (elt instanceof Property){
			return new PropertyEditPart(graphNode,modelManager);}
		
		//Slot
		if (elt instanceof Slot){
			return new SlotEditPart(graphNode,modelManager);}

		//Comment
		if (elt instanceof Comment){
			return new CommentEditPart(graphNode,modelManager);}

		//Opaque Expression
		if (elt instanceof OpaqueExpression){
			return new OpaqueExpressionEditPart(graphNode,modelManager);}

		// else
		return null;
	}
	

}
